package com.apes.scm.voucher.service;

import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.OutboxEventService;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.EventUtil;
import com.apes.framework.util.MapUtil;
import com.apes.project.jekunAuto.timeTask.BaseService;
import com.apes.scm.invoice.model.Invoice;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.repository.VoucherRepository;
import com.apes.scm.voucher.service.builder.VoucherBuilder;
import com.apestech.framework.json.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 功能：凭证服务
 *
 * @author xul
 * @create 2018-10-17 15:41
 */
@Service
public class VoucherService extends DomainService {
    @Autowired
    BaseService baseService;

    @Autowired
    VoucherRepository voucherRepository;

    /**
     * 功能：创建凭证
     */
    public Voucher create(SimpleRequest simpleRequest) {
        Voucher voucher = simpleRequest.getO(Voucher.class);
        return save(voucher);
    }

    public Voucher save(Voucher voucher) {
        VoucherBuilder builder = getVoucherBuilder(voucher.getBusinessType());
        if (voucher.getDept() != null && voucher.getCompany() != null && !voucher.getDept().getCompany().equals(voucher.getCompany())) {
            throw new RuntimeException("部门所属公司与凭证公司不一致！");
        }
        voucher = builder.create(voucher);
        sendSourceBusinessData(voucher);    // 发送写入凭证事件
        pushMessageForCalculateFee(voucher);
        return voucher;
    }

    /**
     * 功能：凭证冲销
     */
    public Voucher writeOff(SimpleRequest request) {
        String id = request.get("id");
        Voucher voucher = voucherRepository.findOne(id);
        if(voucher == null){
            throw new RuntimeException("业务凭证不存在！");
        }
        return writeOffVoucher(voucher);
    }

    /**
     * 功能：凭证冲销
     */
    public Voucher writeOffVoucher(Voucher voucher) {
        VoucherBuilder builder = getVoucherBuilder(voucher.getBusinessType());
        return builder.writeOff(voucher);
    }

    private VoucherBuilder getVoucherBuilder(String businessType) {
        VoucherBuilder builder = VoucherUtil.getBusinessExecutor(VoucherBuilder.class, businessType);
        if (builder == null) throw new RuntimeException("业务单据类型：" + businessType + " 没有定义凭证构造器！");
        return builder;
    }

    private void sendSourceBusinessData(Voucher voucher) {
        if (Objects.isNull(voucher)) return;
        Map<String, Object> map = new HashMap<>();
        map.put("id", voucher.getSource());
        map.put("businessType", voucher.getSourceBusinessType());
        map.put("voucherType", voucher.getVoucherType());

        List<Map<String, Object>> items = voucher.getVoucherItems().stream()
                .map(voucherItem -> {
                    Map<String, Object> m = new HashMap<>();
                    m.put("id", voucherItem.getSourceItemId());
                    m.put("originItemId", voucherItem.getOriginItemId());
                    m.put("qty", voucherItem.getProductQty());
                    m.put("supplierId", voucherItem.getInventoryBatch() != null ?  voucherItem.getInventoryBatch().getSupplier().getId() : "");
                    m.put("batchId", voucherItem.getInventoryBatch() != null ? voucherItem.getInventoryBatch().getId() : "");
                    return m;
                }).collect(Collectors.toList());

        map.put("items", items);
        EventUtil.sendSynEvent(this, "event:voucher.save.qtyVouched", map);
    }

    /**
     * 通过凭证生成账单
     *
     * @param request {"id": voucherId}
     * @return Invoice
     */
    public Invoice createInvoice(SimpleRequest request) {
        String id = request.get("id");
        Voucher voucher = voucherRepository.findOne(id);
        return invoke("invoice.create", MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(voucher))));
    }


    /***
     * 推送计算平台服务费消息
     */

    public void pushMessageForCalculateFee(Voucher voucher) {
        if (Objects.isNull(voucher)) return;
        try {
            Map msg = MapUtil.mapper("id", voucher.getId());

            OutboxPayloadWrapper wrapper = new OutboxPayloadWrapper();
            wrapper.setSubscriber("fn.partnerCheck.calculateVoucherFee");
            wrapper.setAggregateId(voucher.getId());
            try {
                wrapper.setPayload(JSON.toJSONString(msg));
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage());
            }
            SpringManager.getBean(OutboxEventService.class).sendSaveEvent(wrapper);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取本期入库
     *
     * @param request
     * @return
     */
    public JSONObject storageNumber(SimpleRequest request) throws ParseException {
        JSONObject jo = request.getJO();
        Object node = node(jo);

        String inventory;
        if("代销".equals(((JSONObject) node).get("COOPERATION").toString()) ){
            inventory="IM_CONSIGN";
        }else{
            inventory="IM_OWN";
        }
        //取结果集
        Date createDate = new SimpleDateFormat("yyyy-MM-dd").parse(String.valueOf(((JSONObject) node).get("CREATE_DATE").toString()));
        List<Map> resultList = voucherRepository.findStorageNumber(((JSONObject) node).get("PRODUCT_ID").toString(),inventory,
                ((JSONObject) node).get("COMPANY_ID").toString(),createDate );
        JSONObject object = new JSONObject();
        object.put("content", resultList);
        object.put("total", resultList.size());
        return object;
    }

    /**
     * 获取本期入库月
     *
     * @param request
     * @return
     */
    public JSONObject storageMonth(SimpleRequest request) throws ParseException {
        JSONObject jo = request.getJO();
        Object node = node(jo);
        String inventory;
        if(((JSONObject) node).get("COOPERATION").toString().equals("代销")){
            inventory="IM_CONSIGN";
        }else{
            inventory="IM_OWN";
        }
        //取结果集
        List<Map> resultList = voucherRepository.findStorageMonth(((JSONObject) node).get("PRODUCT_ID").toString(), inventory,
                ((JSONObject) node).get("COMPANY_ID").toString(), ((JSONObject) node).get("CREATE_DATE").toString());
        JSONObject object = new JSONObject();
        object.put("content", resultList);
        object.put("total", resultList.size());
        return object;
    }

    public Object node(JSONObject jo){
        Object node =null;
        if(jo.get("node")==null){
            JSONObject data = (JSONObject) jo.get("data");
            node = data.get("node");
        }else{
            node=jo.get("node");
        }
        return node;
    }

    /**
     * 获取本期返厂
     *
     * @param request
     * @return
     */
    public JSONObject purchaseReturn(SimpleRequest request) throws ParseException {
        JSONObject jo = request.getJO();
        Object node = node(jo);
        String inventory;
        if(((JSONObject) node).get("COOPERATION").toString().equals("代销")){
            inventory="IM_CONSIGN";
        }else{
            inventory="IM_OWN";
        }
        //取结果集
        Date createDate = new SimpleDateFormat("yyyy-MM-dd").parse(String.valueOf(((JSONObject) node).get("CREATE_DATE").toString()));
        List<Map> resultList = voucherRepository.findPurchaseReturn(((JSONObject) node).get("PRODUCT_ID").toString(),inventory,
                ((JSONObject) node).get("COMPANY_ID").toString(),createDate );
        JSONObject object = new JSONObject();
        object.put("content", resultList);
        object.put("total", resultList.size());
        return object;
    }

    /**
     * 获取本期返厂月
     *
     * @param request
     * @return
     */
    public JSONObject purchaseReturnMonth(SimpleRequest request) throws ParseException {
        JSONObject jo = request.getJO();
        Object node = node(jo);
        String inventory;
        if(((JSONObject) node).get("COOPERATION").toString().equals("代销")){
            inventory="IM_CONSIGN";
        }else{
            inventory="IM_OWN";
        }
        //取结果集
        List<Map> resultList = voucherRepository.findPurchaseReturnMonth(((JSONObject) node).get("PRODUCT_ID").toString(),inventory,
                ((JSONObject) node).get("COMPANY_ID").toString(),((JSONObject) node).get("CREATE_DATE").toString() );
        JSONObject object = new JSONObject();
        object.put("content", resultList);
        object.put("total", resultList.size());
        return object;
    }

    /**
     * 获取本期损溢
     *
     * @param request
     * @return
     */
    public JSONObject profitAndLoss(SimpleRequest request) throws ParseException {
        JSONObject jo = request.getJO();
        Object node = node(jo);
        String inventory;
        if(((JSONObject) node).get("COOPERATION").toString().equals("代销")){
            inventory="IM_CONSIGN";
        }else{
            inventory="IM_OWN";
        }
        //取结果集
        Date createDate = new SimpleDateFormat("yyyy-MM-dd").parse(String.valueOf(((JSONObject) node).get("CREATE_DATE").toString()));
        List<Map> resultList = voucherRepository.findProfitAndLoss(((JSONObject) node).get("PRODUCT_ID").toString(),inventory,
                ((JSONObject) node).get("COMPANY_ID").toString(),createDate );
        JSONObject object = new JSONObject();
        object.put("content", resultList);
        object.put("total", resultList.size());
        return object;
    }

    /**
     * 获取本期损溢
     *
     * @param request
     * @return
     */
    public JSONObject profitAndLossMonth(SimpleRequest request) throws ParseException {
        JSONObject jo = request.getJO();
        Object node = node(jo);
        String inventory;
        if(((JSONObject) node).get("COOPERATION").toString().equals("代销")){
            inventory="IM_CONSIGN";
        }else{
            inventory="IM_OWN";
        }
        //取结果集
        List<Map> resultList = voucherRepository.findProfitAndLossMonth(((JSONObject) node).get("PRODUCT_ID").toString(),inventory,
                ((JSONObject) node).get("COMPANY_ID").toString(),((JSONObject) node).get("CREATE_DATE").toString()  );
        JSONObject object = new JSONObject();
        object.put("content", resultList);
        object.put("total", resultList.size());
        return object;
    }

    /**
     * 获取本期调拨
     *
     * @param request
     * @return
     */
    public JSONObject findTran(SimpleRequest request) throws ParseException {
        JSONObject jo = request.getJO();
        Object node = node(jo);
        String inventory;
        if(((JSONObject) node).get("COOPERATION").toString().equals("代销")){
            inventory="IM_CONSIGN";
        }else{
            inventory="IM_OWN";
        }
        //取结果集
        Date createDate = new SimpleDateFormat("yyyy-MM-dd").parse(String.valueOf(((JSONObject) node).get("CREATE_DATE").toString()));
        List<Map> resultList = voucherRepository.findTran(((JSONObject) node).get("PRODUCT_ID").toString(),inventory,
                ((JSONObject) node).get("COMPANY_ID").toString(),createDate );
        JSONObject object = new JSONObject();
        object.put("content", resultList);
        object.put("total", resultList.size());
        return object;
    }

    /**
     * 获取本期调拨
     *
     * @param request
     * @return
     */
    public JSONObject findTranMonth(SimpleRequest request) throws ParseException {
        JSONObject jo = request.getJO();
        Object node = node(jo);
        String inventory;
        if(((JSONObject) node).get("COOPERATION").toString().equals("代销")){
            inventory="IM_CONSIGN";
        }else{
            inventory="IM_OWN";
        }
        //取结果集
        List<Map> resultList = voucherRepository.findTranMonth(((JSONObject) node).get("PRODUCT_ID").toString(),inventory,
                ((JSONObject) node).get("COMPANY_ID").toString(),((JSONObject) node).get("CREATE_DATE").toString()  );
        JSONObject object = new JSONObject();
        object.put("content", resultList);
        object.put("total", resultList.size());
        return object;
    }

    /**
     * 获取本期销售
     *
     * @param request
     * @return
     */
    public JSONObject findSale(SimpleRequest request) throws ParseException {
        JSONObject jo = request.getJO();
        Object node = node(jo);
        //取结果集
        Date createDate = new SimpleDateFormat("yyyy-MM-dd").parse(String.valueOf(((JSONObject) node).get("CREATE_DATE").toString()));
        List<Map> resultList = voucherRepository.findSale(((JSONObject) node).get("PRODUCT_ID").toString(),
                ((JSONObject) node).get("COMPANY_ID").toString(),createDate );
        JSONObject object = new JSONObject();
        object.put("content", resultList);
        object.put("total", resultList.size());
        return object;
    }

    /**
     * 获取本期销售
     *
     * @param request
     * @return
     */
    public JSONObject findSaleMonth(SimpleRequest request) throws ParseException {
        JSONObject jo = request.getJO();
        Object node = node(jo);
        //取结果集
        List<Map> resultList = voucherRepository.findSaleMonth(((JSONObject) node).get("PRODUCT_ID").toString(),
                ((JSONObject) node).get("COMPANY_ID").toString(),((JSONObject) node).get("CREATE_DATE").toString()  );
        JSONObject object = new JSONObject();
        object.put("content", resultList);
        object.put("total", resultList.size());
        return object;
    }

}
